#include "stdafx.h"
#include "FileOrganizerT.h"          // 包含文件整理器头文件
#include <QDir>                     // 包含目录操作类
#include <QFile>                    // 包含文件操作类
#include <QDateTime>                // 包含日期时间类
#include <QApplication>             // 包含QApplication类
#include <windows.h>                // 包含Windows API
#include <shlobj.h>                 // 包含Shell API

FileOrganizer::FileOrganizer(QObject* parent)
    : QObject(parent)               // 调用父类构造函数
    , totalSize(0)                  // 初始化总大小为0
{
    desktopPath = getDesktopPath();  // 获取桌面路径
}

QString FileOrganizer::getDesktopPath()
{
    wchar_t path[MAX_PATH];  // 定义路径缓冲区
    // 调用Windows API获取桌面路径
    if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_DESKTOP, NULL, 0, path))) {
        return QString::fromWCharArray(path);  // 成功则转换为QString返回
    }
    return QString();  // 失败返回空字符串
}

void FileOrganizer::scanDesktopFiles()
{
    fileList.clear();        // 清空文件列表
    categoryStats.clear();   // 清空分类统计
    totalSize = 0;          // 重置总大小

    QDir desktopDir(desktopPath);  // 创建桌面目录对象
    if (!desktopDir.exists()) {    // 检查桌面目录是否存在
        emit errorOccurred("无法访问桌面目录");  // 发射错误信号
        emit operationFinished();  // 发射完成信号
        return;
    }

    // 获取桌面所有文件（排除目录和特殊文件）
    QFileInfoList files = desktopDir.entryInfoList(
        QDir::Files | QDir::NoDotAndDotDot, QDir::Name);

    int totalFiles = files.size();  // 总文件数
    int processed = 0;              // 已处理文件数

    foreach(const QFileInfo & fileInfo, files) {  // 遍历文件
        FileInfo info = getFileInfo(fileInfo);    // 获取文件信息
        fileList.append(info);                    // 添加到文件列表

        // 更新分类统计
        categoryStats[info.category]++;

        // 更新总大小
        totalSize += info.size;

        processed++;  // 增加处理计数
        int progress = (processed * 100) / totalFiles;  // 计算进度

        // 发射进度更新信号
        emit progressUpdated(progress,
            QString("正在扫描文件: %1/%2").arg(processed).arg(totalFiles));

        QApplication::processEvents();  // 处理事件，保持UI响应
    }

    emit operationFinished();  // 发射完成信号
}

FileInfo FileOrganizer::getFileInfo(const QFileInfo& fileInfo)
{
    FileInfo info;                    // 创建文件信息结构体
    info.name = fileInfo.fileName();  // 设置文件名
    info.path = fileInfo.filePath();  // 设置文件路径
    info.category = getFileCategory(fileInfo.fileName());  // 设置文件分类
    info.size = fileInfo.size();      // 设置文件大小
    info.sizeString = formatFileSize(fileInfo.size());  // 设置格式化大小
    info.extension = fileInfo.suffix().toLower();  // 设置扩展名（小写）
    info.lastModified = fileInfo.lastModified().toString("yyyy-MM-dd hh:mm:ss");  // 设置修改时间

    return info;  // 返回文件信息
}

QString FileOrganizer::getFileCategory(const QString& filename)
{
    QString extension = QFileInfo(filename).suffix().toLower();  // 获取小写扩展名

    // 文档类型
    if (extension == "pdf" || extension == "doc" || extension == "docx" ||
        extension == "txt" || extension == "rtf" || extension == "xls" ||
        extension == "xlsx" || extension == "ppt" || extension == "pptx") {
        return "文档";
    }
    // 图片类型
    else if (extension == "jpg" || extension == "jpeg" || extension == "png" ||
        extension == "gif" || extension == "bmp" || extension == "ico" ||
        extension == "svg") {
        return "图片";
    }
    // 视频类型
    else if (extension == "mp4" || extension == "avi" || extension == "mkv" ||
        extension == "mov" || extension == "wmv" || extension == "flv") {
        return "视频";
    }
    // 音频类型
    else if (extension == "mp3" || extension == "wav" || extension == "flac" ||
        extension == "aac" || extension == "ogg" || extension == "wma") {
        return "音频";
    }
    // 压缩文件
    else if (extension == "zip" || extension == "rar" || extension == "7z" ||
        extension == "tar" || extension == "gz") {
        return "压缩文件";
    }
    // 可执行文件
    else if (extension == "exe" || extension == "msi" || extension == "bat" ||
        extension == "cmd") {
        return "应用程序";
    }
    else {
        return "其他";
    }
}

QString FileOrganizer::formatFileSize(qint64 size)
{
    // 格式化文件大小显示
    if (size < 1024) {
        return QString("%1 B").arg(size);
    }
    else if (size < 1024 * 1024) {
        return QString("%1 KB").arg(size / 1024.0, 0, 'f', 1);
    }
    else if (size < 1024 * 1024 * 1024) {
        return QString("%1 MB").arg(size / (1024.0 * 1024.0), 0, 'f', 1);
    }
    else {
        return QString("%1 GB").arg(size / (1024.0 * 1024.0 * 1024.0), 0, 'f', 1);
    }
}

void FileOrganizer::organizeByType()
{
    // 按分类排序文件列表
    std::sort(fileList.begin(), fileList.end(),
        [](const FileInfo& a, const FileInfo& b) {
            if (a.category == b.category) {
                return a.name.toLower() < b.name.toLower();  // 同分类按名称排序
            }
            return a.category < b.category;  // 按分类排序
        });

    emit operationFinished();  // 发射完成信号
}

void FileOrganizer::organizeByExtension()
{
    // 按扩展名排序文件列表
    std::sort(fileList.begin(), fileList.end(),
        [](const FileInfo& a, const FileInfo& b) {
            if (a.extension == b.extension) {
                return a.name.toLower() < b.name.toLower();  // 同扩展名按名称排序
            }
            return a.extension < b.extension;  // 按扩展名排序
        });

    emit operationFinished();  // 发射完成信号
}

bool FileOrganizer::createCategoryFolders()
{
    // 获取所有分类
    QSet<QString> categories;
    foreach(const FileInfo & file, fileList) {
        categories.insert(file.category);
    }

    // 为每个分类创建文件夹
    foreach(const QString & category, categories) {
        QString folderPath = desktopPath + "/" + category;
        QDir dir(folderPath);

        if (!dir.exists()) {  // 如果文件夹不存在
            if (!dir.mkpath(".")) {  // 创建文件夹
                emit errorOccurred(QString("无法创建文件夹: %1").arg(folderPath));
                return false;
            }
        }
    }

    return true;
}

void FileOrganizer::moveFilesToCategories()
{
    if (!createCategoryFolders()) {  // 先创建分类文件夹
        emit operationFinished();    // 失败则发射完成信号
        return;
    }

    int totalFiles = fileList.size();  // 总文件数
    int movedCount = 0;                // 已移动文件数
    int errorCount = 0;                // 错误计数

    foreach(const FileInfo & file, fileList) {  // 遍历文件列表
        QString sourcePath = file.path;  // 源文件路径
        QString destPath = desktopPath + "/" + file.category + "/" + file.name;  // 目标路径

        QFile sourceFile(sourcePath);  // 创建源文件对象
        if (sourceFile.exists()) {     // 如果源文件存在
            if (sourceFile.rename(destPath)) {  // 重命名（移动）文件
                movedCount++;  // 增加成功计数
            }
            else {
                errorCount++;  // 增加错误计数
                emit errorOccurred(QString("移动文件失败: %1").arg(file.name));
            }
        }

        movedCount++;  // 增加处理计数
        int progress = (movedCount * 100) / totalFiles;  // 计算进度

        // 发射进度更新信号
        emit progressUpdated(progress,
            QString("正在移动文件: %1/%2 (错误: %3)").arg(movedCount).arg(totalFiles).arg(errorCount));

        QApplication::processEvents();  // 处理事件，保持UI响应
    }

    // 重新扫描更新文件列表
    scanDesktopFiles();
}